#ifndef _NODE_LIST_H_
#define _NODE_LIST_H_

#include "../define/define.h"
#include "../util/threadtimer.h"
#include "../util/timer.h"
#include "./node.h"
#include "./buffer.h"
#include "../util/log.h"
#include "../util/lock.h"

class TimeSink;

class Node_list : public TimeSink
{
public:
	Node_list()
	{
        m_log = new logfile("Node_list");

		memset(m_con,0,sizeof(uint32) * max_node_count);
		m_buffer.create(0,0);
	}

	~Node_list()
	{
	    delete m_log;
		for(uint32 i =0; i<max_node_count; i++)
		{
			if (m_con[i] != 0)
	           delete m_con[i];
		}
	}

	bool init(UDPServer* udp,uint32 socket,uint32 d_socket,uint8 cmd)
	{
		m_udp      = udp;

		m_s_socket = socket;

		m_d_socket = d_socket;
      
		m_pdu      = cmd;

		m_buffer.set_socket(socket);
		
		add_sink(this,1);

		return true;
	}

	bool free()
	{
		del_sink(this);
		
		 m_buffer.reset();

		for(uint32 i =0; i<max_node_count; i++)
		{
			if (m_con[i] != 0)
	           delete m_con[i];
		}
		
		memset(&m_ipnode,0,sizeof(ip_node));
		m_udp = NULL;
		m_s_socket = 0;
		m_d_socket = 0;
      
		m_pdu      = 0;
	}

	bool send_down_over()
	{
		func_lock locker;
		for(uint32 i=0; i<max_node_count; i++)
		{	
			if(m_con[i] == 0)
				continue;
		
			m_con[i]->send_down_over();
		}
		return true;
	}

	bool set_over()
	{
		m_buffer.set_big_id();
	}

	bool send_down_err(uint32 last_id)
	{
		func_lock locker;
		for(uint32 i=0; i<max_node_count; i++)
		{	
			if(m_con[i] == 0)
				continue;
		
			m_con[i]->send_down_err(last_id);
		}
		return true;
	}

	bool send_route()
	{
		func_lock locker;
		for(uint32 i=0; i<max_node_count; i++)
		{	
			if(m_con[i] == 0)
				continue;
					
			m_con[i]->send_route();
		}
        return true;
	}

	bool add_trans(ip_node node,Link_info trans,uint32 con_id)
	{
		func_lock locker;
		node.trans_link[con_id] = trans;
		m_con[con_id] = new Node_info(con_id,node,m_udp,m_s_socket,m_d_socket,m_pdu);
	    return true;
	}

	bool set_d_socket(uint32 d_socket)
	{
		func_lock locker;
		for(uint32 i=0; i<max_node_count; i++)
		{	
			if(m_con[i] == 0)
				continue;
		
			m_con[i]->set_d_socket(d_socket);
		}

		m_d_socket = d_socket;
        return true; 
	}

	bool add_node(ip_node node)
	{
		func_lock locker;
		m_ipnode = node;
		for(uint32 i =0; i<1; i++)
		{
			/*char tt[1024] = {0};
			sprintf(tt,"node.count=%d,node.trans_link[i].count=%d,i=%d,m_udp=%x",
				node.count,node.trans_link[i].count,i,m_udp);
			m_log->WriteTrace(tt);*/

			if (m_con[i] != 0)
				continue;

			if(node.trans_link[i].count == 0)
				continue;

			m_con[i] = new Node_info(i,node,m_udp,m_s_socket,m_d_socket,m_pdu);
		}

		send_route();
		return true;
	}

	bool ack_data( uint32 socket , uint16 con_id ,
		char* buf, uint32 buf_size)
	{ 
		func_lock locker;
		ip_node  node;
		ByteStream ctrl((uint8*)buf,0,buf_size);
		uint8  pduver =0;
		uint8  pduname =0;
		uint32 conn_id =0;
		uint32 r_count =0;
		uint32 socket1 =0;
		ctrl >> pduver;
		ctrl >> pduname;
		ctrl >> node.count;
		ctrl >> node.l_port;
        ctrl >> node.d_ip;
		ctrl >> node.d_port;
        ctrl >> conn_id;
		ctrl >> m_s_socket;
		ctrl >> m_d_socket;
		uint32 ip_id;
		ctrl >>ip_id;
		ctrl >> r_count;
		uint32 tmp_ip[8];
	    for(uint32 i=0; i<r_count;i++)
			ctrl>>tmp_ip[i];
		
		data_node tempnode;
		ctrl >> tempnode.date_id;
		ctrl >> tempnode.buf_size;
		uint32 time = m_buffer.del_packet(&tempnode);
	    return m_con[con_id]->ack_pack_list(time);
	}

	bool put_data(char* buf, uint32 buf_size)
	{
		func_lock locker;
		return m_buffer.put_packet(buf,buf_size);
	}

	bool read_data(char* buf, uint32* buf_size)
	{
		func_lock locker;
		return m_buffer.read_data(buf,buf_size);
	}

	bool is_full()
	{
		return m_buffer.is_full();
	}
	
private:

    void OnTimer()
	{
		func_lock locker;
	    data_node node[128];

		uint32 rt = m_buffer.send_over();

		if(rt != 0xffffffff)
			send_down_err(rt);
		
		for(uint32 i=0; i<max_node_count; i++)
		{	
			if(m_con[i] == 0)
				continue;

			m_con[i]->add_tick(get_time());		
		    m_buffer.set_tick(get_time());
			
			uint32 time = m_con[i]->ping_time();

			if(get_time() % 1000 == 0)
			{
				float con_speed= m_con[i]->get_speed();
				char tmp_str[1024] = {0};
  				sprintf(tmp_str,"speed=%f",con_speed);
	    		//m_log->WriteTrace(tmp_str);
			}

			uint32 n = m_con[i]->get_down_count();
	
			if(n > 0 && n <= 128)
            {		
				uint32 count = m_buffer.get_packet_id(n,node,time);
							
				if(count > 0)
				{
					if(m_con[i]->send(node,count) == true)
					{
					    /*char tmp_str[1024] = {0};
  						sprintf(tmp_str,"this_time=%d,this=%x,i=%d,m_s_socket=%d,n=%d,time=%d,con_id=%d,count=%d",
							get_time(),this,i,m_s_socket,n,time,i,count);
	    				m_log->WriteTrace(tmp_str);*/
					}
				}
			}

		}
	}

	Node_info*  m_con[max_node_count];
	buffer      m_buffer;

	UDPServer*  m_udp;
	uint32      m_s_socket;

	logfile*    m_log;
	uint8       m_pdu;
	
	uint32      m_d_socket;
    ip_node     m_ipnode;
};

#endif